package com.igl.talk.android.client.core.handlers;/*
 * @author Adam Wieczorek 
 *
 * 26/03/2014
 *
 * All rights reserved.
 */

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;
import com.google.gson.JsonElement;
import com.igl.talk.android.client.core.model.MessageModel;
import com.igl.talk.android.client.core.model.UserModel;
import com.igl.talk.android.client.ide.notifications.NotificationsFactory;
import microsoft.aspnet.signalr.client.*;
import microsoft.aspnet.signalr.client.http.android.AndroidPlatformComponent;
import microsoft.aspnet.signalr.client.hubs.HubConnection;
import microsoft.aspnet.signalr.client.hubs.HubProxy;

import java.util.ArrayList;
import java.util.List;

public class IncomingMessagesHandler extends Handler implements HandlerInteface {

    private static IncomingMessagesHandler instance = null;

    private UserModel currentUser;
    private Context context;
    private Messenger client;
    private Logger logger = new Logger() {

        @Override
        public void log(String message, LogLevel level) {
            //Log.d("ChatServiceIncomingHandler", "MessageModel: " + message);
        }
    };
    private HubConnection conn;
    private HubProxy proxy;

    private boolean isApplicationStopped = false;
    private int unreadMessagesCounter = 0;
    private int notificationId = -1;

    private IncomingMessagesHandler(Context context) {
        this.context = context;
    }

    public static IncomingMessagesHandler getInstance(Context context) {
        if (instance == null) {
            instance = new IncomingMessagesHandler(context);
        }
        return instance;
    }

    private boolean start(final String userName) {
        try {
            Platform.loadPlatformComponent((PlatformComponent) new AndroidPlatformComponent());
            conn = new HubConnection("http://wujowojtas.azurewebsites.net/", "", true, logger);
            proxy = conn.createHubProxy("ChatHub");
            proxy.subscribe(new Object() {
                @SuppressWarnings("unused")
                public void messageReceived(String name, String message) {
                    Log.d("ChatServiceIncomingHandler", "ChatMessage: " + name+" "+message);
                }
            });

            // Subscribe to the error event
            conn.error(new ErrorCallback() {

                @Override
                public void onError(Throwable error) {
                    Log.e("ChatServiceIncomingHandler", "ChatMessage: " + error.getMessage());
                }
            });

            // Subscribe to the connected event
            conn.connected(new Runnable() {

                @Override
                public void run() {
                    Log.d("ChatServiceIncomingHandler", "ChatMessage: Connected");
                }
            });

            // Subscribe to the closed event
            conn.closed(new Runnable() {

                @Override
                public void run() {
                    Log.d("ChatServiceIncomingHandler", "ChatMessage: Disconnected");
                }
            });

            // Start the connection
            conn.start()
                    .done(new Action<Void>() {

                        @Override
                        public void run(Void obj) throws Exception {
                            Log.d("ChatServiceIncomingHandler", "ChatMessage: Done connecting!");

                            proxy.invoke("Register", userName).done(new Action<Void>() {

                                @Override
                                public void run(Void obj) throws Exception {
                                    Log.d("ChatServiceIncomingHandler", "ChatMessage: Registered as a new user!");
                                }
                            });
                            currentUser = new UserModel(userName);

                            //	conn.stop();
                        }
                    });


            // Subscribe to the received event
            conn.received(new MessageReceivedHandler() {

                @Override
                public void onMessageReceived(JsonElement json) {
                    Log.d("ChatServiceIncomingHandler", "JSON: " + json.toString());
                    String actionType = json.getAsJsonObject().get("M").toString();
                    String userNickname;
                /*   if (actionType.equals("\"registered\""))
                   {
                       String userNickname=json.getAsJsonObject().get("A").getAsJsonArray().get(0).toString();
                       userJoined();
                       sendJSON_ToClient(userNickname);
                   }
                   else*/
                    if (actionType.equals("\"newUserJoined\"")) {
                        userNickname = json.getAsJsonObject().get("A").getAsJsonArray().get(0)
                                .getAsJsonObject().get("Name").toString().replace('\"', ' ');
                        userJoined(new UserModel(userNickname));
                        updateUsersList(json.getAsJsonObject().get("A").getAsJsonArray().get(1));
                    } else if (actionType.equals("\"userLoggedOut\"")) {
                        userNickname = json.getAsJsonObject().get("A").getAsJsonArray().get(0)
                                .getAsJsonObject().get("Name").toString().replace('\"', ' ');
                        userLeaved(new UserModel(userNickname));
                        updateUsersList(json.getAsJsonObject().get("A").getAsJsonArray().get(1));
                    } else if (actionType.equals("\"newMessage\"")) {
                        String content=json.getAsJsonObject().get("A").getAsJsonArray().get(0)
                                .getAsJsonObject().get("Text").toString().replace('\"', ' ');
                        userNickname=json.getAsJsonObject().get("A").getAsJsonArray().get(0)
                                .getAsJsonObject().get("User").getAsJsonObject().get("Name")
                                .toString().replace("\"", "");

                        //old JSON format
                        //userNickname = json.getAsJsonObject().get("A").getAsJsonArray().get(0).toString().replace('\"', ' ');
                        //String content = json.getAsJsonObject().get("A").getAsJsonArray().get(1).toString().replace('\"', ' ');
                        UserModel user = new UserModel(userNickname);
                        MessageModel message = new MessageModel(user, content);
                        receivedNewMessage(message);
                    } else {
                        sendJSON_ToClient(json.toString());
                    }


                }
            });
        } catch (Exception e) {
            Log.e("ChatServiceIncomingHandler", "ChatMessage: Exception during connecting to server");
            return false;
        }
        return true;
    }


    private void updateUsersList(JsonElement usersListDirtyTemp) {
        List<UserModel> currentUsers = new ArrayList<UserModel>();
        for (JsonElement userName : usersListDirtyTemp.getAsJsonArray()) {
            currentUsers.add(new UserModel(userName.getAsJsonObject().get("Name").toString().replace('\"', ' ')));
        }

       /* String usersListCleanTemp = usersListDirtyTemp.replace('\"', ' ').replace('[', ' ').replace(']', ' ').replace('\\', ' ').replaceAll("\\s+", "");
        String[] usersListTemp = usersListCleanTemp.split(",");

        for (String userName : usersListTemp) {
            currentUsers.add(new User(userName));
        }*/
        if (client != null) {
            try {
                Message androidMessage = Message.obtain(null,
                        MSG_USER_LIST, 0, 0);
                androidMessage.obj = currentUsers;
                client.send(androidMessage);
            } catch (RemoteException e) {
                Log.e("ChatServiceIncomingHandler", "ChatMessage: " + e.getStackTrace());
            }
        }
    }
/*    private void updateUsersList(String usersListDirtyTemp) {
        List<User> currentUsers = new ArrayList<User>();
        String usersListCleanTemp = usersListDirtyTemp.replace('\"', ' ').replace('[', ' ').replace(']', ' ').replace('\\', ' ').replaceAll("\\s+", "");
        String[] usersListTemp = usersListCleanTemp.split(",");

        for (String userName : usersListTemp) {
            currentUsers.add(new User(userName));
        }
        if (client != null) {
            try {
                Message message = Message.obtain(null,
                        MSG_USER_LIST, 0, 0);
                message.obj = currentUsers;
                client.send(message);
            } catch (RemoteException e) {
                Log.e("ChatServiceIncomingHandler", "ChatMessage: " + e.getStackTrace());
            }
        }
    }*/

    private void receivedNewMessage(MessageModel message) {
        if (client != null) {
            try {
                Message androidMessage = Message.obtain(null,
                        MSG_RECEIVED_MESSAGE, 0, 0);
                androidMessage.obj = message;
                client.send(androidMessage);
            } catch (RemoteException e) {
                Log.e("ChatServiceIncomingHandler", "ChatMessage: " + e.getStackTrace());
            }
        }
        if (isApplicationStopped) {
            unreadMessagesCounter++;
            if (notificationId == -1) {
                notificationId = NotificationsFactory.NEW_MESSAGE.notify(context, unreadMessagesCounter);
            } else {
                NotificationsFactory.NEW_MESSAGE.updateNotification(context, notificationId, unreadMessagesCounter);
            }
        } else {
            unreadMessagesCounter = 0;
            notificationId = -1;
        }
    }


    private void sendJSON_ToClient(String json) {
        if (client != null) {
            try {
                Message message = Message.obtain(null,
                        MSG_JSON, 0, 0);
                message.obj = json;
                client.send(message);
            } catch (RemoteException e) {
                Log.e("ChatServiceIncomingHandler", "ChatMessage: " + e.getStackTrace());
            }
        }
    }

    private void userJoined(UserModel newUser) {
        if (client != null) {
            try {
                Message message = Message.obtain(null,
                        MSG_NEW_USER_JOINED, 0, 0);
                message.obj = newUser;
                client.send(message);
            } catch (RemoteException e) {
                Log.e("ChatServiceIncomingHandler", "ChatMessage: " + e.getStackTrace());
            }
        }
    }

    private void userLeaved(UserModel user) {
        if (client != null) {
            try {
                Message androidMessage = Message.obtain(null,
                        MSG_USER_LEAVED, 0, 0);
                androidMessage.obj = user;
                client.send(androidMessage);
            } catch (RemoteException e) {
                Log.e("ChatServiceIncomingHandler", "ChatMessage: " + e.getStackTrace());
            }
        }
    }


    private void stop() {
        if (conn != null) {
            conn.stop();
        }
        currentUser = null;
    }

    @Override
    public void handleMessage(Message androidMessage) {
        switch (androidMessage.what) {
/*            case MSG_SAY_HELLO:
                Toast.makeText(context, "hello!", Toast.LENGTH_SHORT).show();
                break;*/
            case MSG_PLEASE_RESPOND:
                Toast.makeText(context, "Service got please respond!", Toast.LENGTH_SHORT).show();
                if (client != null) {
                    try {
                        int tempValue = 5;
                        client.send(Message.obtain(null,
                                MSG_RESPONSE, tempValue, 0));
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case MSG_MAKE_SERVICE_CLIENT_IPC:
                client = androidMessage.replyTo;
                break;
            case MSG_REGISTER_NEW_USER:
                start(androidMessage.obj.toString());
                break;
            case MSG_LOGOUT:
                stop();
                break;
            case MSG_SEND_MESSAGE:
                sendMessageFromClient(androidMessage.obj.toString());
                break;
            default:
                super.handleMessage(androidMessage);
        }
    }

    private void sendMessageFromClient(String message) {

       /* Not Implemented yet!*/
        if (proxy != null) {
            try {
                proxy.invoke("SendMessage", currentUser.getName(), message).done(new Action<Void>() {

                    @Override
                    public void run(Void obj) throws Exception {
                        Log.d("ChatServiceIncomingHandler", "Message sent!");
                    }
                });
            } catch (Exception e) {
                Log.e("ChatServiceIncomingHandler", "ChatMessage: " + e.getStackTrace());

            }
        }
    }

    public boolean isApplicationStopped() {
        return isApplicationStopped;
    }

    public void setApplicationStopped(boolean isApplicationStopped) {
        this.isApplicationStopped = isApplicationStopped;
    }
}
